| prefix_filter |string |`::/0` | Only advertise on-link prefixes within the provided IPv6 prefix; others are filtered out. [IPv6 prefix] |
| ntp |list |`<local address>`| NTP servers to announce accepts IPv4 and IPv6 |
| upstream |list | - | A list of interfaces which can be used as a source of configuration information (e.g. for NTP servers, if not set explicitly). |
-| captive_portal_uri |string | no | The API URI to be sent in RFC8910 captive portal options, via DHCPv6 and ICMPv6 RA. |
+| captive_portal_uri |string | no | The API URI to be sent in RFC8910 captive portal options, via DHCPv4, DHCPv6, and ICMPv6 RA. |
[//]: # "dhcpv6_raw - string - not documented, may change when generic DHCPv4/DHCPv6 options are added"
if ((c = tb[IFACE_ATTR_CAPTIVE_PORTAL_URI])) {
iface->captive_portal_uri = strdup(blobmsg_get_string(c));
iface->captive_portal_uri_len = strlen(iface->captive_portal_uri);
+ if (iface->captive_portal_uri_len > UINT8_MAX) {
+ warn("RFC8910 captive portal URI > %d characters for interface '%s': option via DHCPv4 not possible",
+ UINT8_MAX,
+ iface->name);
+ }
debug("Set RFC8910 captive portal URI: '%s' for interface '%s'",
iface->captive_portal_uri, iface->name);
}
IOV_FR_NONCE_CAP,
IOV_DNR,
IOV_DNR_BODY,
+ IOV_CAPTIVE_PORTAL,
IOV_END,
IOV_PADDING,
IOV_TOTAL
[IOV_FR_NONCE_CAP] = { &reply_fr_nonce_cap, 0 },
[IOV_DNR] = { &reply_dnr, 0 },
[IOV_DNR_BODY] = { NULL, 0 },
+ [IOV_CAPTIVE_PORTAL] = { NULL, 0 },
[IOV_END] = { &reply_end, sizeof(reply_end) },
[IOV_PADDING] = { NULL, 0 },
};
DHCPV4_OPT_CLIENTID, // Must be in reply if present in req, RFC6842, §3
DHCPV4_OPT_AUTHENTICATION,
DHCPV4_OPT_SEARCH_DOMAIN,
+ DHCPV4_OPT_CAPTIVE_PORTAL,
DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE,
};
iov[IOV_DNR_BODY].iov_base = dnrs;
iov[IOV_DNR_BODY].iov_len = dnrs_len;
break;
+
+ case DHCPV4_OPT_CAPTIVE_PORTAL:
+ size_t uri_len = iface->captive_portal_uri_len;
+ if (uri_len == 0 || uri_len > UINT8_MAX)
+ break;
+
+ uint8_t *buf = alloca(2 + uri_len);
+ struct dhcpv4_option *opt = (struct dhcpv4_option *)buf;
+
+ opt->code = DHCPV4_OPT_CAPTIVE_PORTAL;
+ opt->len = uri_len;
+ memcpy(opt->data, iface->captive_portal_uri, uri_len);
+
+ iov[IOV_CAPTIVE_PORTAL].iov_base = opt;
+ iov[IOV_CAPTIVE_PORTAL].iov_len = 2 + uri_len;
+ break;
}
}
DHCPV4_OPT_CLIENTID = 61,
DHCPV4_OPT_USER_CLASS = 77,
DHCPV4_OPT_AUTHENTICATION = 90,
+ DHCPV4_OPT_CAPTIVE_PORTAL = 114, // RFC8910
DHCPV4_OPT_SEARCH_DOMAIN = 119,
DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE = 145,
DHCPV4_OPT_DNR = 162,